Shell语法

2020.8 星期 :

基础

变量

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh
echo "Hello World !"
echo -e arg #执行arg里的转义字符。echo加-e默认会换行
echo arg > myfile #显示结果重定向至文件,会生成myfile文件
your_name="Qzx"
echo $your_name
echo ${your_name}
### 变量名外加花括号是可选的,主要为了帮助解释器识别变量的边界
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done

变量删除:unset variable_name。
变量类型:
局部变量:在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问。
环境变量:所有的程序,包括shell启动的程序,都能访问环境变量。
shell变量:shell变量是由shell程序设置的特殊变量。

输出设置为变量

Shell 也支持将命令的执行结果赋值给变量,常见的有以下两种方式:

1
2
variable=`command`
variable=$(command)

第一种方式把命令用反引号包围起来,反引号和单引号非常相似,容易产生混淆,所以不推荐使用这种方式;
第二种方式把命令用$()包围起来,区分更加明显,所以推荐使用这种方式。

1
2
logsth=$(echo 'test')
echo $logsth

系统变量

字符串操作

单引号字符串限制:
单引号里的任何字符串都会原样输出,单引号字符串中的变量是无效的
单引号字符串中不能出现单引号(对单引号使用转义字符也不行)

双引号字符串:
双引号可以有变量
双引号可以出现转义字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
### 单双引号
### 拼接字符串
your_name="woo"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
### 获取字符串长度
string="abcd"
echo ${#string} #输出:4
### 提取子字符串
string="alibaba is a great company"
echo ${string:1:4} #输出:liba

### 查找子字符串
# 找出字母i在这句话中的位置,要在linux下运行,mac下会报错
string="alibaba is a great company"
echo `expr index "$string" is` #输出:3

Shell 数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    # 在Shell中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
# 数组名=(值1 值2 ... 值n)
array_name=(value0 value1 value2 value3)
# 也可以单独定义数组的各个分量,可使用不连续的下标,且下标范围没有限制
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

# 读取数组
# 一般格式 ${数组名[下标]}
valuen=${array_name[n]}
# 使用@符号可以获取数组中的所有元素
echo ${array_name[@]}

# 获取数组的长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
length=${#array_name[n]}

Shell基本运算符

1
2
3
4
5
6
7
8
9
10
a=10
b=20
`expr $a + $b` 加法 结果为 30。
`expr $a - $b` 减法 结果为 -10。
`expr $a \* $b` 乘法 结果为 200。
`expr $b / $a` 除法 结果为 2。
`expr $b % $a` 取余 结果为 0。
`a=$b` 赋值 将变量b的值赋给 a。
`[$a == $b]` 相等 结果返回 false
`[$a != $b]` 不相等 结果返回 true

Shell里的流程控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    # if else

if condition1
then
command1
elif condition2
command2
else
commandN
fi
# 写成一行(适用于终端命令提示符)
if `ps -ef | grep ssh`; then echo hello; fi

# for while

for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done

while condition
do
command
done

if和then写在同一行时,需要分号分隔。分号是 Bash 的命令分隔符。它们也可以写成两行,这时不需要分号。
true和false是两个特殊命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 if true; then echo 'hello world'; fi

# 如果用户输入3,就会连续判断3次。
echo -n "输入一个1到3之间的数字(包含两端)> "
read character
if [ "$character" = "1" ]; then
echo 1
elif [ "$character" = "2" ]; then
echo 2
elif [ "$character" = "3" ]; then
echo 3
else
echo 输入不符合要求
fi

test 命令

if结构的判断条件,一般使用test命令,有三种形式。
是等价的,但是第三种形式还支持正则判断,前两种不支持。
实际上,[这个字符是test命令的一种简写形式,可以看作是一个独立的命令,这解释了为什么它后面必须有空格。

1
2
3
4
5
6
7
8
# 写法一
test expression

# 写法二
[ expression ]

# 写法三
[[ expression ]]

判断表达式

if关键字后面,跟的是一个命令。这个命令可以是test命令,也可以是其他命令。命令的返回值为0表示判断成立,否则表示不成立。因为这些命令主要是为了得到返回值,所以可以视为表达式。

常用的判断表达式有下面这些。

文件判断
字符串判断

以下表达式用来判断字符串。

[ string ]:如果string不为空(长度大于0),则判断为真。
[ -n string ]:如果字符串string的长度大于零,则判断为真。
[ -z string ]:如果字符串string的长度为零,则判断为真。
[ string1 = string2 ]:如果string1和string2相同,则判断为真。
[ string1 == string2 ] 等同于[ string1 = string2 ]。
[ string1 != string2 ]:如果string1和string2不相同,则判断为真。
[ string1 ‘>’ string2 ]:如果按照字典顺序string1排列在string2之后,则判断为真。
[ string1 ‘<’ string2 ]:如果按照字典顺序string1排列在string2之前,则判断为真。
注意,test命令内部的>和<,必须用引号引起来(或者是用反斜杠转义)。否则,它们会被 shell 解释为重定向操作符。

整数判断

下面的表达式用于判断整数。

[ integer1 -eq integer2 ]:如果integer1等于integer2,则为true。
[ integer1 -ne integer2 ]:如果integer1不等于integer2,则为true。
[ integer1 -le integer2 ]:如果integer1小于或等于integer2,则为true。
[ integer1 -lt integer2 ]:如果integer1小于integer2,则为true。
[ integer1 -ge integer2 ]:如果integer1大于或等于integer2,则为true。
[ integer1 -gt integer2 ]:如果integer1大于integer2,则为true。

正则判断

[[ expression ]]这种判断形式,支持正则表达式。

[[ string1 =~ regex ]]
上面的语法中,regex是一个正则表示式,=~是正则比较运算符。

3.5 test 判断的逻辑运算
3.6 算术判断

Bash 还提供了((…))作为算术条件,进行算术运算的判断。

1
2
3
if ((3 > 2)); then
echo "true"
fi

3.7 普通命令的逻辑运算

可以使用 Bash 的命令控制操作符&&(AND)和||(OR),进行多个命令的逻辑运算。

case 结构

1
2
3
4
5
6
7
case expression in
pattern )
commands ;;
pattern )
commands ;;
...
esac

常见操作

1
2
3
4
5
# 获取当前目录名:
basename `pwd`
echo ${PWD##*/}
# 获取当前 git 分支名
git_name=$(git symbolic-ref --short HEAD)

knowledge is no pay,reward is kindness
0%